//
//
// @Auther: by wujehy
// @Email:wujehy@qq.com
// @Data:20-1-15
// @Time:上午11:02
//

#include "FileConfig.h"
#include "rapidjson/pointer.h"
#include "rapidjson/prettywriter.h"
#include <rapidjson/istreamwrapper.h>
#include <rapidjson/ostreamwrapper.h>
#include <fstream>

// 构造一个 查询 json 的 元素的方法
static auto FindJsonDataFromString(rapidjson::Document &d, std::string jsonKey) -> std::string {
    // 判断 元素 是否在 json 里面
//    rapidjson::Pointer(path.c_str()).Set(d,value.c_str());
    if (rapidjson::Pointer(jsonKey.c_str()).Get(d) != nullptr) {
        if (rapidjson::Pointer(jsonKey.c_str()).Get(d)->IsString()) {
            return rapidjson::Pointer(jsonKey.c_str()).Get(d)->GetString();
        } else {
            throw "The value on the path is not the string type";
        }
    } else {
        throw "No value on the path";
    }
};

static auto FindJsonDataFromUint32 = [](rapidjson::Document &d, std::string jsonKey) -> uint32_t {
    // 判断 元素 是否在 json 里面
//    rapidjson::Pointer(path.c_str()).Set(d,value.c_str());
    if (rapidjson::Pointer(jsonKey.c_str()).Get(d) != nullptr) {
        if (rapidjson::Pointer(jsonKey.c_str()).Get(d)->IsUint()) {
            return rapidjson::Pointer(jsonKey.c_str()).Get(d)->GetUint();
        } else {
            throw "The value on the path is not the uint32_t type";
        }
    } else {
        throw "No value on the path";
    }
};
static auto FindJsonDataFromInt32 = [](rapidjson::Document &d, std::string jsonKey) -> int32_t {
    // 判断 元素 是否在 json 里面
    if (rapidjson::Pointer(jsonKey.c_str()).Get(d) != nullptr) {
        if (rapidjson::Pointer(jsonKey.c_str()).Get(d)->IsInt()) {
            return rapidjson::Pointer(jsonKey.c_str()).Get(d)->GetInt();
        } else {
            throw "The value on the path is not the int32_t type";
        }
    } else {
        throw "No value on the path";
    }
};

static auto FindJsonDataFromInt64 = [](rapidjson::Document &d, std::string jsonKey) -> int64_t {
    if (rapidjson::Pointer(jsonKey.c_str()).Get(d) != nullptr) {
        if (rapidjson::Pointer(jsonKey.c_str()).Get(d)->IsInt64()) {
            return rapidjson::Pointer(jsonKey.c_str()).Get(d)->GetInt64();
        } else {
            throw "The value on the path is not the int64_t type";
        }
    } else {
        throw "No value on the path";
    }
};

static auto FindJsonDataFromUInt64 = [](rapidjson::Document &d, std::string jsonKey) -> uint64_t {
    if (rapidjson::Pointer(jsonKey.c_str()).Get(d) != nullptr) {
        if (rapidjson::Pointer(jsonKey.c_str()).Get(d)->IsUint64()) {
            return rapidjson::Pointer(jsonKey.c_str()).Get(d)->GetUint64();
        } else {
            throw "The value on the path is not the uint64_t type";
        }
    } else {
        throw "No value on the path";
    }
};

static auto FindJsonDataFromFloat(rapidjson::Document &d, std::string jsonKey) -> float {

    if (rapidjson::Pointer(jsonKey.c_str()).Get(d) != nullptr) {
        if (rapidjson::Pointer(jsonKey.c_str()).Get(d)->IsFloat()) {
            return rapidjson::Pointer(jsonKey.c_str()).Get(d)->GetFloat();
        } else {
            throw "The value on the path is not the float type";
        }
    } else {
        throw "No float  value on the path";
    }
};

static auto FindJsonDataFromDouble(rapidjson::Document &d, std::string jsonKey) -> double {

    if (rapidjson::Pointer(jsonKey.c_str()).Get(d) != nullptr) {
        if (rapidjson::Pointer(jsonKey.c_str()).Get(d)->IsDouble()) {
            return rapidjson::Pointer(jsonKey.c_str()).Get(d)->GetDouble();
        } else {
            throw "The value on the path is not the double type";
        }
    } else {
        throw "No value on the path";
    }
};


FileConfig::~FileConfig() {
    std::cout << "delete FileConfig Success" << std::endl;
}

FileConfig::FileConfig(std::string configPath) {
    if (configPath.empty()) {
        // 使用默认的路径
        currentConfigPath = "./FileConfig.json";
    } else {
        currentConfigPath = configPath;
    }
    std::fstream fs;
    fs.open(currentConfigPath, std::ios::in | std::ios::out);
    rapidjson::IStreamWrapper isw(fs);
    document.ParseStream(isw);
    // 关闭文件流
    fs.close();
    std::cout << "init FileConfig Success path:" << currentConfigPath << std::endl;
}

int FileConfig::changePath(std::string configPath, bool saveOldConfig) {
    if (saveOldConfig) {
        saveDataInLocal();
    }
    if (configPath.empty()) {
        // 使用默认的路径
        currentConfigPath = "./FileConfig.json";
    } else {
        currentConfigPath = configPath;
    }
    std::fstream fs;
    fs.open(currentConfigPath, std::ios::in);
    rapidjson::IStreamWrapper isw(fs);
    document.ParseStream(isw);
    // 关闭文件流
    fs.close();
    return 0;
}

int FileConfig::Read(std::string path, std::string &value) {
    try {
        value = FindJsonDataFromString(document, path);
        return EXIT_SUCCESS;
    } catch (char const *errData) {
        std::cout << "error :" << errData << std::endl;
        return EXIT_FAILURE;
    }
}


int FileConfig::Read(std::string path, int32_t &value) {
    try {
        value = FindJsonDataFromInt32(document, path);
        return EXIT_SUCCESS;
    } catch (char const *errData) {
        std::cout << "error :" << errData << std::endl;

        return EXIT_FAILURE;
    }
}

int FileConfig::Read(std::string path, uint32_t &value) {
    try {
        value = FindJsonDataFromUint32(document, path);
        return EXIT_SUCCESS;
    } catch (char const *errData) {
        std::cout << "error :" << errData << std::endl;
        return EXIT_FAILURE;
    }
}

int FileConfig::Read(std::string path, int64_t &value) {
    try {
        value = FindJsonDataFromInt64(document, path);
        return EXIT_SUCCESS;
    } catch (char const *errData) {
        std::cout << "error :" << errData << std::endl;
        return EXIT_FAILURE;
    }
}

int FileConfig::Read(std::string path, uint64_t &value) {
    try {
        value = FindJsonDataFromUInt64(document, path);
        return EXIT_SUCCESS;
    } catch (char const *errData) {
        std::cout << "error :" << errData << std::endl;
        return EXIT_FAILURE;
    }
}

int FileConfig::Read(std::string path, float &value) {
    try {
        value = FindJsonDataFromFloat(document, path);
        return EXIT_SUCCESS;
    } catch (char const *errData) {
        std::cout << "error :" << errData << std::endl;
        return EXIT_FAILURE;
    }
}

int FileConfig::Read(std::string path, double &value) {
    try {
        value = FindJsonDataFromDouble(document, path);
        return EXIT_SUCCESS;
    } catch (char const *errData) {
        std::cout << "error :" << errData << std::endl;
        return EXIT_FAILURE;
    }
}

int FileConfig::Write(std::string path, std::string value, bool saveFile) {
    //    // 路径不能为空
    if (path.empty()) {
        std::cout << "path is empty";
        return EXIT_FAILURE;
    }

    rapidjson::Pointer(path.c_str()).Set(document, value.c_str());
    if (saveFile) {
        //保存到文件
        try {
            saveDataInLocal();
        } catch (const char *errMsg) {
            std::cout << "wornning :" << errMsg << std::endl;
        }
    }
    return EXIT_SUCCESS;
}

int FileConfig::Write(std::string path, int64_t value, bool saveFile) {
    if (path.empty()) {
        std::cout << "path is empty";
        return EXIT_FAILURE;
    }

    rapidjson::Pointer(path.c_str()).Set(document, value);
    if (saveFile) {
        //保存到文件
        try {
            saveDataInLocal();
        } catch (const char *errMsg) {
            std::cout << "wornning :" << errMsg << std::endl;
        }
    }
    return EXIT_SUCCESS;
}

int FileConfig::WriteUInt64(std::string path, uint64_t value, bool saveFile) {
    if (path.empty()) {
        std::cout << "path is empty";
        return EXIT_FAILURE;
    }

    rapidjson::Pointer(path.c_str()).Set(document, value);
    if (saveFile) {
        //保存到文件
        try {
            saveDataInLocal();
        } catch (const char *errMsg) {
            std::cout << "wornning :" << errMsg << std::endl;
        }
    }
    return EXIT_SUCCESS;
}

int FileConfig::WriteDouble(std::string path, double value, bool saveFile) {
    if (path.empty()) {
        std::cout << "path is empty";
        return EXIT_FAILURE;
    }

    rapidjson::Pointer(path.c_str()).Set(document, value);
    if (saveFile) {
        //保存到文件
        try {
            saveDataInLocal();
        } catch (const char *errMsg) {
            std::cout << "wornning :" << errMsg << std::endl;
        }
    }
    return EXIT_SUCCESS;
}


void FileConfig::saveDataInLocal() {
    if (currentConfigPath.empty()) {
        throw "currentConfigPath is empty";
    }
    std::fstream fs;
    fs.open(currentConfigPath, std::ios::out | std::ios::trunc);
    rapidjson::OStreamWrapper osw(fs);
    rapidjson::PrettyWriter<rapidjson::OStreamWrapper> writer(osw);
    document.Accept(writer);
    fs.close();
}
